﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Description;


namespace advadev.DataStorage
{

    /// <summary>
    /// Represents a generic entity service data storage
    /// </summary>
    public class GenericEntityServiceDataStorage : IGenericEntityDataStorage
    {

        /// <summary>for internal use</summary>
        private string _administratorUserName;
        /// <summary>for internal use</summary>
        private string _administratorPassword;


        /// <summary>
        /// Initializes a new instance of the GenericEntityServiceDataStorage
        /// class by the given parameter
        /// </summary>
        /// <param name="applicationKey">
        /// Application key
        /// </param>
        /// <param name="endpointConfigurationName">
        /// Endpoint configuration name
        /// </param>
        /// <param name="serviceUserName">
        /// Service user name
        /// </param>
        /// <param name="servicePassword">
        /// Service password
        /// </param>
        /// <param name="administratorUserName">
        /// Administrator user name
        /// </param>
        /// <param name="administratorPassword">
        /// Administrator password
        /// </param>
        /// <exception cref="ArgumentException">
        /// Will be thrown if the endpoint configuration is invalid
        /// </exception>
        public GenericEntityServiceDataStorage(string applicationKey, string endpointConfigurationName, string serviceUserName, string servicePassword)
            : this(applicationKey, endpointConfigurationName, serviceUserName, servicePassword, null, null)
        {
        }

        /// <summary>
        /// Initializes a new instance of the GenericEntityServiceDataStorage
        /// class by the given parameter
        /// </summary>
        /// <param name="applicationKey">
        /// Application key
        /// </param>
        /// <param name="endpointConfigurationName">
        /// Endpoint configuration name
        /// </param>
        /// <param name="serviceUserName">
        /// Service user name
        /// </param>
        /// <param name="servicePassword">
        /// Service password
        /// </param>
        /// <exception cref="ArgumentException">
        /// Will be thrown if the endpoint configuration is invalid
        /// </exception>
        public GenericEntityServiceDataStorage(string applicationKey, string endpointConfigurationName, string serviceUserName, string servicePassword, string administratorUserName, string administratorPassword)
        {
            _administratorUserName = administratorUserName;
            _administratorPassword = administratorPassword;
            try
            {
                ChannelFactory<IDataStorageService> service = new ChannelFactory<IDataStorageService>(endpointConfigurationName);
                service.Credentials.UserName.UserName = serviceUserName;
                service.Credentials.UserName.Password = servicePassword;
                DataStorageService = service.CreateChannel();
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, "endpointConfigurationName");
            }
        }


        /// <summary>
        /// Gets or sets the data storage service
        /// </summary>
        private IDataStorageService DataStorageService
        {
            get;
            set;
        }


        #region IGenericEntityDataStorage implementation
        /// <summary>
        /// Saves the given generic entity
        /// </summary>
        /// <param name="genericEntity">
        /// Generic entity to save
        /// </param>
        public void Save(GenericEntity genericEntity)
        {
            DataStorageService.Save(genericEntity);
        }

        /// <summary>
        /// Saves the given list of generic entities
        /// </summary>
        /// <param name="genericEntities">
        /// List of generic entities to save
        /// </param>
        public void Save(IList<GenericEntity> genericEntities)
        {
            DataStorageService.Save(genericEntities);
        }

        /// <summary>
        /// Finds the generic entity with the given id, application key and type
        /// </summary>
        /// <param name="id">
        /// Id of the generic entity
        /// </param>
        /// <param name="applicationKey">
        /// Application key
        /// </param>
        /// <param name="fullClassName">
        /// Full class name of the type
        /// </param>
        /// <returns>
        /// The generic entity or null
        /// </returns>
        public GenericEntity Find(string id, string applicationKey, string fullClassName)
        {
            return DataStorageService.Find(id, applicationKey, fullClassName);
        }

        /// <summary>
        /// Selects all generic entities with the given application key and type
        /// </summary>
        /// <param name="applicationKey">
        /// Application key
        /// </param>
        /// <param name="fullClassName">
        /// Full class name of the type
        /// </param>
        /// <returns>
        /// A list of generic entities
        /// </returns>
        public IList<GenericEntity> Select(string applicationKey, string fullClassName)
        {
            return DataStorageService.Select(applicationKey, fullClassName);
        }

        /// <summary>
        /// Deletes the given generic entity
        /// </summary>
        /// <param name="genericEntity">
        /// Generic entity to delete
        /// </param>
        public void Delete(GenericEntity genericEntity)
        {
            DataStorageService.Delete(genericEntity);
        }

        /// <summary>
        /// Deletes the given list of generic entities
        /// </summary>
        /// <param name="genericEntities">
        /// List of generic entities to delete
        /// </param>
        public void Delete(IList<GenericEntity> genericEntities)
        {
            DataStorageService.Delete(genericEntities);
        }

        /// <summary>
        /// Deletes all generic entities with the given application key and type
        /// </summary>
        /// <param name="applicationKey">
        /// Application key
        /// </param>
        /// <param name="fullClassName">
        /// Full class name of the type
        /// </param>
        public void Delete(string applicationKey, string fullClassName)
        {
            DataStorageService.Delete(applicationKey, fullClassName);
        }

        /// <summary>
        /// Deletes all generic entities with the given application key
        /// </summary>
        /// <param name="applicationKey">
        /// Application key
        /// </param>
        public void Delete(string applicationKey)
        {
            DataStorageService.Delete(applicationKey);
        }

        /// <summary>
        /// Finds all full class names with the given application key
        /// </summary>
        /// <param name="applicationKey">
        /// Application key
        /// </param>
        /// <returns>
        /// List of full class names or empty list
        /// </returns>
        public IList<string> FindFullClassNames(string applicationKey)
        {
            return DataStorageService.FindFullClassNames(applicationKey);
        }

        /// <summary>
        /// Finds all application keys
        /// </summary>
        /// <returns>
        /// List of application keys or empty list
        /// </returns>
        public IList<string> FindApplicationKeys()
        {
            ClientCredentials administratorCredentials = new ClientCredentials();
            administratorCredentials.UserName.UserName = _administratorUserName;
            administratorCredentials.UserName.Password = _administratorPassword;
            return DataStorageService.FindApplicationKeys(administratorCredentials);
        }
        #endregion IGenericEntityDataStorage implementation

    }

}
